/*********************************************************
          File Name:function_pointer_and_template.cpp
          Author: Abby Cin
          Mail: abbytsing@gmail.com
          Created Time: Sat 19 Dec 2015 07:10:37 PM CST
**********************************************************/

#include <iostream>
#include <string>

using std::string;

template<typename T>
auto plus(T &i) -> decltype(i)
{
        return i;       // return `reference of i`
}

// C++ 'Type Transformation', advanced topic in `type_traits.h`
template<typename T>
auto self(T &i) -> typename std::remove_reference<decltype(i)>::type
{
        return i;       // return `copy of i`
}


struct X
{
        typedef int (*ifp)(int, int);
        typedef string (*sfp)(string, string);

        void factory(ifp fp)
        {
                std::cout << fp(1, 2) << std::endl;
        }

        void factory(sfp sp)
        {
                std::cout << sp("1", "2") << std::endl;
        }
};

template<typename T>
auto add(T a, T b) -> decltype(a)
{
        return a + b;
}

int main()
{
        int a = 1;
        int b = 1;

        plus(a) += 1;
        self(b);

        struct X x;

        // wrong, compiler don't know which version of `factory` to call
        // x.factory(add);

        x.factory(add<int>);
        x.factory(add<string>);

        std::cout << a  << "\t" << b << std::endl;

        return 0;
}
